package roboSoccer;

import java.io.*;
import java.util.Scanner;

/**
 * Stores all representations of objects on the field, retrieves messages from
 * the vision system, updates positions of the objects on the field, and calls
 * the AI routines for our team.
 * 
 * @author Ben Hopkins
 * 
 */
public class GameState {

	// game objects
	/**
	 * An array of each team in the game; the teams store the RoboPlayer
	 * objects.
	 */
	public RoboTeam[] teams;
	/**
	 * The ball FieldObject.
	 */
	public FieldObject ball;

	/**
	 * This is the virtual world in the case of a simulated game.
	 */
	public SimulationHandler sim;
	
	/**
	 * Left goal line
	 */
	public static final Line leftGoal = new Line(new Vector(67,67+405/2-70/2), new Vector(0,70));
	
	/**
	 * Right goal line
	 */
	public static final Line rightGoal = new Line(new Vector(605+67,67+405/2-70/2), new Vector(0,70));
	
	/**
	 * Left end line
	 */
	public static final Line leftEnd = new Line(new Vector(67,67), new Vector(0,405));
	
	/**
	 * Right end line
	 */
	public static final Line rightEnd = new Line(new Vector(67+605,67), new Vector(0,405));
	
	/**
	 * Left quarter line
	 */
	public static final Line leftQuarter = new Line(new Vector(67+605/4,67), new Vector(0,405));
	
	/**
	 * Right quarter line
	 */
	public static final Line rightQuarter = new Line(new Vector(67+605*3/4,67), new Vector(0,405));
	
	/**
	 * Midline
	 */
	public static final Line midline = new Line(new Vector(67+605/2, 67), new Vector(0, 405));
	
	/**
	 * Top line
	 */
	public static final Line topLine = new Line(new Vector(67,67), new Vector(605,0));
	
	/**
	 * Bottom line
	 */
	public static final Line bottomLine = new Line(new Vector(67,67+405), new Vector(605,0));
	
	// variables used for communication
	private File comFile;
	private Scanner scanner;
	private int frameNumber;
	/**
	 * The total number of frames that have been processed by the program from
	 * the camera. This is equivalent to the number of game loops.
	 */
	public int totalFrames;

	/**
	 * Stores the teams and the ball and initializes other class variables.
	 * 
	 * @param teams
	 *            An array of RoboTeam objects. Each refers to a team on the
	 *            field.
	 * @param ball
	 *            The ball object that will be used in this game.
	 */
	public GameState(RoboTeam[] teams, FieldObject ball) {
		// the same instance of these variables is stored for use in this class
		this.teams = teams;
		this.ball = ball;

		// this variables tracks the frame number being returned from the vision
		frameNumber = 0;

		// open the communication file
		try {
			comFile = new File("GrabDemo/Vs6/comFile.txt");
			scanner = new Scanner(comFile);
		} catch (Exception e) {
			System.out.println("Error reading comFile.txt");
		}

	}
	
	/**
	 * Sets the game to be a simulated game.
	 */
	public void setSimulation()
	{
		sim = new SimulationHandler(teams);
	}
	
	/**
	 * Sets the game to be a game with NXT robots.
	 */
	public void setNXT()
	{
		teams[0].setNXT();
	}

	/**
	 * Updates the positions of the objects on the field, grabbing this
	 * information from the vision, and then executes the update method on our
	 * team.
	 */
	public void update() {
		// the first task is to read the communication file until
		// we see that a new frame has been computed by the vision.
		boolean ready = false;
		// The timeOut value will process the old frame again if no new one
		// comes
		// for a number of loops. This is mostly for testing and should probably
		// be removed when working with the real updating frames.
		int timeOut = 0;
		while (!ready && timeOut < 1000) {
			timeOut++;
			int newFrameNumber = 0;
			try {
				scanner = new Scanner(comFile);
				// if the frame number returned is different, we know the vision
				// has returned new values
				newFrameNumber = scanner.nextInt();
				if (frameNumber < newFrameNumber) {
						frameNumber = newFrameNumber;
						ready = true;
				}
			} catch (Exception e) {
				ready = false;
			}
		}

		// here we take the perception of the vision and update the objects
		// on our virtual field.
		for (int i = 0; i < teams[0].players.length; i++) {
			teams[0].players[i].updatePosition(new Vector(scanner.nextInt(),
					scanner.nextInt(), scanner.nextInt()));
		}
		for (int i = 0; i < teams[1].players.length; i++) {
			teams[1].players[i].updatePosition(new Vector(scanner.nextInt(),
					scanner.nextInt(), scanner.nextInt()));
		}
		ball.updatePosition(new Vector(scanner.nextInt(), scanner.nextInt()));

		// here we call the AI update on the team, and the other team if it's a simulation
		teams[0].update(this);
		if(sim != null)
			teams[1].update(this);
		
		// if it is a simulated game, call update on the simulated world
		if(sim != null)
			sim.update();
			
		// increment the total number of frames
		totalFrames++;
	}

}
